﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

namespace WcfDynamicProxy
{
    /// <summary>
    /// Фабрика асинхронных интерфейсов. Создает асинхронные интерфейсы из синхронных.
    /// </summary>
    internal class AsyncServiceInterfaceFactory
    {
        private static readonly Lazy<AsyncServiceInterfaceFactory> singleton =
            new Lazy<AsyncServiceInterfaceFactory>(() => new AsyncServiceInterfaceFactory(), true);

        private readonly ModuleBuilder module;
        private readonly Dictionary<Type, Type> generated = new Dictionary<Type, Type>();

        public AsyncServiceInterfaceFactory()
        {
            var assemblyName = new AssemblyName("Silverlight.WCF.AutoGeneratedAsyncInterfaces");

            AppDomain appDomain = AppDomain.CurrentDomain;
            AssemblyBuilder assemblyBuilder = appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);

            module = assemblyBuilder.DefineDynamicModule("Silverlight.WCF.AutoGeneratedAsyncInterfaces.dll");
        }

        public static AsyncServiceInterfaceFactory Instance
        {
            get { return singleton.Value; }
        }

        public Type Generate(Type syncInterface)
        {
            lock (generated)
            {
                if (!generated.ContainsKey(syncInterface))
                    generated[syncInterface] = GenerateAsyncInterface(syncInterface);

                return generated[syncInterface];
            }
        }

        private Type GenerateAsyncInterface(Type syncInterface)
        {
            var generator = new AsyncServiceInterfaceGenerator(module, syncInterface);
            return generator.Generate();
        }
    }
}